1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.collect.testing;
18
19 import static com.google.common.collect.Lists.newArrayList;
20 import static com.google.common.collect.testing.IteratorFeature.MODIFIABLE;
21 import static java.util.Collections.emptyList;
22
23 import com.google.common.annotations.GwtCompatible;
24 import com.google.common.collect.ImmutableList;
25 import com.google.common.collect.Lists;
26
27 import junit.framework.AssertionFailedError;
28 import junit.framework.TestCase;
29
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.NoSuchElementException;
33
34
35
36
37
38
39 @GwtCompatible
40 @SuppressWarnings("serial")
41 public class IteratorTesterTest extends TestCase {
42
43 public void testCanCatchDifferentLengthOfIteration() {
44 IteratorTester<Integer> tester =
45 new IteratorTester<Integer>(4, MODIFIABLE, newArrayList(1, 2, 3),
46 IteratorTester.KnownOrder.KNOWN_ORDER) {
47 @Override protected Iterator<Integer> newTargetIterator() {
48 return Lists.newArrayList(1, 2, 3, 4).iterator();
49 }
50 };
51 assertFailure(tester);
52 }
53
54 public void testCanCatchDifferentContents() {
55 IteratorTester<Integer> tester =
56 new IteratorTester<Integer>(3, MODIFIABLE, newArrayList(1, 2, 3),
57 IteratorTester.KnownOrder.KNOWN_ORDER) {
58 @Override protected Iterator<Integer> newTargetIterator() {
59 return Lists.newArrayList(1, 3, 2).iterator();
60 }
61 };
62 assertFailure(tester);
63 }
64
65 public void testCanCatchDifferentRemoveBehaviour() {
66 IteratorTester<Integer> tester =
67 new IteratorTester<Integer>(3, MODIFIABLE, newArrayList(1, 2),
68 IteratorTester.KnownOrder.KNOWN_ORDER) {
69 @Override protected Iterator<Integer> newTargetIterator() {
70 return ImmutableList.of(1, 2).iterator();
71 }
72 };
73 assertFailure(tester);
74 }
75
76 public void testUnknownOrder() {
77 new IteratorTester<Integer>(3, MODIFIABLE, newArrayList(1, 2),
78 IteratorTester.KnownOrder.UNKNOWN_ORDER) {
79 @Override protected Iterator<Integer> newTargetIterator() {
80 return newArrayList(2, 1).iterator();
81 }
82 }.test();
83 }
84
85 public void testUnknownOrderUnrecognizedElement() {
86 IteratorTester<Integer> tester =
87 new IteratorTester<Integer>(3, MODIFIABLE, newArrayList(1, 2, 50),
88 IteratorTester.KnownOrder.UNKNOWN_ORDER) {
89 @Override protected Iterator<Integer> newTargetIterator() {
90 return newArrayList(2, 1, 3).iterator();
91 }
92 };
93 assertFailure(tester);
94 }
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 static class IteratorWithSunJavaBug6529795<T> implements Iterator<T> {
111 Iterator<T> iterator;
112 boolean nextThrewException;
113 IteratorWithSunJavaBug6529795(Iterator<T> iterator) {
114 this.iterator = iterator;
115 }
116
117 @Override
118 public boolean hasNext() {
119 return iterator.hasNext();
120 }
121
122 @Override
123 public T next() {
124 try {
125 return iterator.next();
126 } catch (NoSuchElementException e) {
127 nextThrewException = true;
128 throw e;
129 }
130 }
131
132 @Override
133 public void remove() {
134 if (nextThrewException) {
135 throw new IllegalStateException();
136 }
137 iterator.remove();
138 }
139 }
140
141 public void testCanCatchSunJavaBug6529795InTargetIterator() {
142 try {
143
144 new IteratorTester<Integer>(4, MODIFIABLE, newArrayList(1, 2),
145 IteratorTester.KnownOrder.KNOWN_ORDER) {
146 @Override protected Iterator<Integer> newTargetIterator() {
147 Iterator<Integer> iterator = Lists.newArrayList(1, 2).iterator();
148 return new IteratorWithSunJavaBug6529795<Integer>(iterator);
149 }
150 }.test();
151 } catch (AssertionFailedError e) {
152 return;
153 }
154 fail("Should have caught jdk6 bug in target iterator");
155 }
156
157 public void testCanWorkAroundSunJavaBug6529795InTargetIterator() {
158 IteratorTester<Integer> tester =
159 new IteratorTester<Integer>(4, MODIFIABLE, newArrayList(1, 2),
160 IteratorTester.KnownOrder.KNOWN_ORDER) {
161 @Override protected Iterator<Integer> newTargetIterator() {
162 Iterator<Integer> iterator = Lists.newArrayList(1, 2).iterator();
163 return new IteratorWithSunJavaBug6529795<Integer>(iterator);
164 }
165 };
166
167
168
169
170
171 tester.ignoreSunJavaBug6529795();
172
173 tester.test();
174 }
175
176 private static final int STEPS = 3;
177 static class TesterThatCountsCalls extends IteratorTester<Integer> {
178 TesterThatCountsCalls() {
179 super(STEPS, MODIFIABLE, newArrayList(1),
180 IteratorTester.KnownOrder.KNOWN_ORDER);
181 }
182 int numCallsToNewTargetIterator;
183 int numCallsToVerify;
184 @Override protected Iterator<Integer> newTargetIterator() {
185 numCallsToNewTargetIterator++;
186 return Lists.newArrayList(1).iterator();
187 }
188 @Override protected void verify(List<Integer> elements) {
189 numCallsToVerify++;
190 super.verify(elements);
191 }
192 }
193
194 public void testVerifyGetsCalled() {
195 TesterThatCountsCalls tester = new TesterThatCountsCalls();
196
197 tester.test();
198
199 assertEquals("Should have verified once per stimulus executed",
200 tester.numCallsToVerify,
201 tester.numCallsToNewTargetIterator * STEPS);
202 }
203
204 public void testVerifyCanThrowAssertionThatFailsTest() {
205 final String message = "Important info about why verify failed";
206 IteratorTester<Integer> tester =
207 new IteratorTester<Integer>(1, MODIFIABLE, newArrayList(1, 2, 3),
208 IteratorTester.KnownOrder.KNOWN_ORDER) {
209 @Override protected Iterator<Integer> newTargetIterator() {
210 return Lists.newArrayList(1, 2, 3).iterator();
211 }
212
213 @Override protected void verify(List<Integer> elements) {
214 throw new AssertionFailedError(message);
215 }
216 };
217 AssertionFailedError actual = null;
218 try {
219 tester.test();
220 } catch (AssertionFailedError e) {
221 actual = e;
222 }
223 assertNotNull("verify() should be able to cause test failure", actual);
224 assertTrue("AssertionFailedError should have info about why test failed",
225 actual.getCause().getMessage().contains(message));
226 }
227
228 public void testMissingException() {
229 List<Integer> emptyList = newArrayList();
230
231 IteratorTester<Integer> tester =
232 new IteratorTester<Integer>(1, MODIFIABLE, emptyList,
233 IteratorTester.KnownOrder.KNOWN_ORDER) {
234 @Override protected Iterator<Integer> newTargetIterator() {
235 return new Iterator<Integer>() {
236 @Override
237 public void remove() {
238
239 }
240 @Override
241 public Integer next() {
242
243 return null;
244 }
245 @Override
246 public boolean hasNext() {
247 return false;
248 }
249 };
250 }
251 };
252 assertFailure(tester);
253 }
254
255 public void testUnexpectedException() {
256 IteratorTester<Integer> tester =
257 new IteratorTester<Integer>(1, MODIFIABLE, newArrayList(1),
258 IteratorTester.KnownOrder.KNOWN_ORDER) {
259 @Override protected Iterator<Integer> newTargetIterator() {
260 return new ThrowingIterator<Integer>(new IllegalStateException());
261 }
262 };
263 assertFailure(tester);
264 }
265
266 public void testSimilarException() {
267 List<Integer> emptyList = emptyList();
268 IteratorTester<Integer> tester =
269 new IteratorTester<Integer>(1, MODIFIABLE, emptyList,
270 IteratorTester.KnownOrder.KNOWN_ORDER) {
271 @Override protected Iterator<Integer> newTargetIterator() {
272 return new Iterator<Integer>() {
273 @Override
274 public void remove() {
275 throw new IllegalStateException() { };
276 }
277 @Override
278 public Integer next() {
279 throw new NoSuchElementException() { };
280 }
281 @Override
282 public boolean hasNext() {
283 return false;
284 }
285 };
286 }
287 };
288 tester.test();
289 }
290
291 public void testMismatchedException() {
292 List<Integer> emptyList = emptyList();
293 IteratorTester<Integer> tester =
294 new IteratorTester<Integer>(1, MODIFIABLE, emptyList,
295 IteratorTester.KnownOrder.KNOWN_ORDER) {
296 @Override protected Iterator<Integer> newTargetIterator() {
297 return new Iterator<Integer>() {
298 @Override
299 public void remove() {
300
301 throw new IllegalArgumentException();
302 }
303 @Override
304 public Integer next() {
305
306 throw new UnsupportedOperationException();
307 }
308 @Override
309 public boolean hasNext() {
310 return false;
311 }
312 };
313 }
314 };
315 assertFailure(tester);
316 }
317
318 private static void assertFailure(IteratorTester<?> tester) {
319 try {
320 tester.test();
321 fail();
322 } catch (AssertionFailedError expected) {
323 }
324 }
325
326 private static final class ThrowingIterator<E> implements Iterator<E> {
327 private final RuntimeException ex;
328
329 private ThrowingIterator(RuntimeException ex) {
330 this.ex = ex;
331 }
332
333 @Override
334 public boolean hasNext() {
335
336 return true;
337 }
338
339 @Override
340 public E next() {
341 ex.fillInStackTrace();
342 throw ex;
343 }
344
345 @Override
346 public void remove() {
347 ex.fillInStackTrace();
348 throw ex;
349 }
350 }
351 }